#pragma once
#include <iostream> 
#include <vector>
#include <semaphore.h>//信号量的头文件
#include <pthread.h>

using namespace std;


//写一个环形队列生产模型
//需要什么？
//生产者不能超过消费者，消费者不能套圈生产者。
//当生产者和消费者同坐标时，只能生产或者写，其他情况下生产和消费者并发执行
template<class T>
class RingQueue
{
public:
    //static int defaultsize=10;
public:
    RingQueue(int size=10)
    :_RingQ(size),_size(size),_c_step(0),_p_step(0)
    {
        sem_init(&_c_date_sem,0,0);
        sem_init(&_p_date_sem,0,size); 
        pthread_mutex_init(&_c_mutex,nullptr);
        pthread_mutex_init(&_p_mutex,nullptr);
    }

    void push(const T& t)
    {
        sem_wait(&_p_date_sem);
        pthread_mutex_lock(&_p_mutex);
        _RingQ[_p_step]=t;
        _p_step++;
        _p_step%=_size;
        pthread_mutex_unlock(&_p_mutex);
        sem_post(&_c_date_sem);
    }

    T pop()
    {
        sem_wait(&_c_date_sem);
        pthread_mutex_lock(&_c_mutex);
        T t=_RingQ[_c_step];
        _c_step++;
        _c_step%=_size;
        pthread_mutex_unlock(&_c_mutex);
        sem_post(&_p_date_sem);
        return t;
    }



    ~RingQueue()
    {
        sem_destroy(&_c_date_sem);
        sem_destroy(&_p_date_sem); 
        pthread_mutex_destroy(&_c_mutex);
        pthread_mutex_destroy(&_p_mutex);
    }
private:
    //1.需要一个队列负责存？？存什么？存节点吗？
    vector<T> _RingQ;
    //2.需要一个尺寸代表队列大小
    int _size;
    //3.生产者和消费者的下标
    int _c_step;
    int _p_step;
    //4.消费者和生产者的信号量
    //信号量的接口是什么？
    sem_t _c_date_sem;
    sem_t _p_date_sem;
    //5.生产者的锁和消费者的锁
    pthread_mutex_t _c_mutex;
    pthread_mutex_t _p_mutex;
};